临界区

一段修改一个数据结构的代码如果运行时被打断导致数据的不完整或者损毁, 则称这 段代码为临界区.

保护临界区最简单的办法就是忽略阻塞或者忽略那些处理函数将要使用或修改特性数 据的信号.

阻塞信号: sigprocmask 和 sigsetops

可以在信号处理者一级或进程一级阻塞信号.

处理者一级

为了处理一个信号的时候阻塞另一个信号, 要设置 struct sigaction 结构中的 sa_mask 成员位, 它在设置处理函数时被传递给 sigaction. sa_mask 是 sigset_t 类型, 它定义了一个信号集.

一个进程的阻塞信号

在任何时候一个进程都有一些信号被阻塞. 注意, 阻塞而不是忽略. 这个信号集就称 为信号挡板(signal mask). 通过 sigprocmask 可以修改这个被阻塞的信号集, sigprocmask 作为一个原子操作根据所给的信号集来修改当前被阻塞的信号集

  sigprocmask
目标 修改当前的信号挡板
头文件 #include <signal.h>
原型 int res = sigprocmask(int how, const sigset_t *sigs, sigset_t *prev)
参数 how 如何修改, sigs 信号列表, prev 之前的信号类表
返回值 0 成功 -1 失败

sigprocmask 修改当前的信号挡板设置, 当 how 的值分别为 SIG_BLOCK, SIG_UNBLOCK 或 SIG_SET 时, *sigs 所指定的信号将被添加,删除或替换. 如果 prev 不是 NULL, 那么之前的信号挡板设置将被复制到 *prev 中.

用 sigsetops 构造信号集

一个 sigset_t 是一个抽象的信号集, 可以通过一些函数来添加或删除信号. 基本函数如下 :

sigemptyset(sigset_t *setp) 清除由 setp 指向的列表中的所有信号. sigfillset(sigset_t *setp) 添加所有的信号到 setp 指向的列表. sigaddset(sigset_t *setp, int signum) 添加 signum 到 setp 指向的列表. sigdelset(sigset_t *setp, int signum) 从 setp 指向的列表中删除 signum 所标示的信号.

例子: 暂时的阻塞用户信号

程序可以用一下代码来暂时的阻塞 SIGINT 和 ISGQUIT 信号:

sigset_t sigs, prevsigs;                    /* define two signal sets */
sigemptyset(&sigs);                         /* turn off all bits */
sigaddset(&sigs, SIGINT);                   /* turn on SIGINT bit */
sigaddset(&sigs, SIGQUIT);                  /* turn on SIGQUIT bit */
sigprocmask(SIG_BLOCK, &sigs, &prevsigs);   /* add that to proc mask */
// .. modify data structure here ..
sigprocmask(SIG_SET, *prevsigs, NULL);

除非目的就是修改获取的资源, 否则释放资源时恢复获取时的状态是个好习惯.

重入代码(Reentrant Code): 递归调用的危险

一个信号处理者或者一个函数, 如果在激活状态能被调用而不引起任何问题就称之为 可重入的.

在通过 sigaction 设置时, 可以通过设置 SA_NODEFER 位来允许处理函数的递归调用 . 反之, 可以通过清除此位来阻塞信号.

如果处理者不是可重入的, 必须阻塞信号. 但是如果阻塞信号, 就有可能丢失信号.

kill: 从另一个进程发送的信号

信号来自间隔计时器,指定驱动,内核或者进程. 一个进程可以通过 kill 系统调用向 另一个进程发送信号:

  kill
目标 向一个进程发送信号
头文件 #include <sys/types.h>/#include <signal.h>
原型 int kill(pid_t pid, int sig)
参数 pid 目标进程pid, sig 要被发送的信号
返回值 0 成功, -1 失败

Unix 有两个信号可以被用户程序使用, 他们是 SIGUSR1 和 SIGUSR2 . 这两个信号没 有预定义任务. 可以使用他们以避免使用已有的预定义语义的信号.